package edu.stanford.prpl.app.prpltalk.ui;

import static java.awt.Font.BOLD;
import static java.awt.Font.PLAIN;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

import javax.imageio.ImageIO;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.stanford.prpl.api.BlobResource;
import edu.stanford.prpl.api.Group;
import edu.stanford.prpl.api.Identity;
import edu.stanford.prpl.api.PRPLAppClient;
import edu.stanford.prpl.app.prpltalk.PRPLTalk;
import edu.stanford.prpl.app.prpltalk.PRPLTalk.AsynchCallback;
import edu.stanford.prpl.app.prpltalk.PRPLTalk.BuddyInfo;
import edu.stanford.prpl.common.util.StreamUtils;
import edu.stanford.prpl.common.util.StringUtils;
import edu.stanford.prpl.common.util.URIUtils;
import edu.stanford.prpl.impl.BlobResourceImpl;

public class SessionWindow extends JFrame {

	private static Log log = LogFactory.getLog(SessionWindow.class);

	PRPLTalk prplTalk;
	PRPLAppClient prplAppClient;
	String sessionId;
	BlobResource resource;

	JList displayList;
	JTextArea sessionInfoTextArea;
	JTextArea messageTextArea;
	JComboBox buddyComboBox;

	JDialog popupBox;
	AsynchCallback callback;

	public SessionWindow(PRPLTalk prplTalk, String sessionId) {
		super(sessionId);
		this.prplTalk = prplTalk;
		this.prplAppClient = prplTalk.getPRPLAppClient();
		this.sessionId = sessionId;
		this.resource = new BlobResourceImpl(prplTalk.sessionId2ResourceURI(sessionId), prplAppClient);

		this.setBounds(600, 0, 640, 640);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.initFrame();
	}

	public void start() {
		this.callback = new AsynchCallback() {
			@Override
			public void callback(String sessionId) {
				log.debug("AsycCallback called for " + sessionId + " . Thread Id is "
						+ Thread.currentThread().getId());
				Message[] messages = prplTalk.getMessages(sessionId, true);
				displayList.setListData(messages);
				displayList.ensureIndexIsVisible(displayList.getModel().getSize() - 1);
			}
		};

		// this.pack();
		this.prplTalk.setWatcher(sessionId, this.callback);
		this.setVisible(true);
	}

	@Override
	public void dispose() {
		prplTalk.removeWatcher(sessionId, this.callback);
		super.dispose();
	}

	protected void initFrame() {

		// Session Information
		JLabel sessionLabel = new JLabel("Session Information");
		sessionLabel.setFont(new Font("Arial", BOLD, 12));

		this.sessionInfoTextArea = new JTextArea();
		sessionInfoTextArea.setBackground(Color.getHSBColor(0.1f, 0.50f, 1f));
		sessionInfoTextArea.setEditable(false);
		String text = getSessionInfo();
		sessionInfoTextArea.setText(text);

		JPanel sessionPanel = new JPanel(new BorderLayout());
		sessionPanel.add(sessionLabel, BorderLayout.NORTH);
		sessionPanel.add(sessionInfoTextArea, BorderLayout.SOUTH);

		// Session Display
		JLabel displayLabel = new JLabel("Message Display");
		displayLabel.setFont(new Font("Arial", BOLD, 12));

		this.displayList = new JList();
		Message[] messages = prplTalk.getMessages(sessionId, true);
		displayList.setListData(messages);
		displayList.setCellRenderer(new MessageListRenderer());

		JScrollPane displayScrollPane = new JScrollPane();
		displayScrollPane.getViewport().add(displayList);
		displayList.ensureIndexIsVisible(displayList.getModel().getSize() - 1);

		JPanel displayPanel = new JPanel(new BorderLayout());
		displayPanel.add(displayLabel, BorderLayout.NORTH);
		displayPanel.add(displayScrollPane, BorderLayout.CENTER);

		// Session Message Compose
		JPanel messagePanel = initMessageCompose();

		this.getContentPane().setLayout(new BorderLayout(2, 2));
		this.getContentPane().add(sessionPanel, BorderLayout.PAGE_START);
		this.getContentPane().add(displayPanel, BorderLayout.CENTER);
		this.getContentPane().add(messagePanel, BorderLayout.PAGE_END);

		this.displayList.addMouseListener(new MouseListener() {
			@Override
			public void mouseClicked(MouseEvent e) {

				Message message = (Message) displayList.getSelectedValue();
				log.debug("Selected to item " + displayList.getSelectedIndex());

				if (message == null)
					return;

				try {

					String messageDesc = StringUtils.trimEvenNull(message.getDescription());

					if (!messageDesc.startsWith(PRPLTalk.MSG_RESOURCE))
						return;

					String resourceURI = message.getContent().toString();

					if (URIUtils.isResourceURI(resourceURI)) {

						BlobResource blobResource = prplAppClient.getResourceManager()
								.getBlobResource(resourceURI);
						log.debug("Try to download a blob for resource URI." + resourceURI);

						JFileChooser fileChooser = new JFileChooser();
						// File f = new File(blobResource.getName());
						// fileChooser.setSelectedFile(f);

						if (JFileChooser.APPROVE_OPTION == fileChooser.showSaveDialog(SessionWindow.this)) {
							try {
								File file = fileChooser.getSelectedFile();
								FileOutputStream fout = new FileOutputStream(file);

								log.debug("Saving: " + file.getName() + ".");
								StreamUtils.copyStream(blobResource.getBlob(), fout);

								// Open immediately if supported
								if (Desktop.isDesktopSupported()) {
									Desktop.getDesktop().open(file);
									log.debug("Opening " + file.getName());
								}
							} catch (IOException ex) {
								ex.printStackTrace();
							}
							showInformationWindow("Successfully downloaded.");
						} else {
							log.debug("Save command cancelled by user.");
						}

					}
				} catch (MessagingException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseReleased(MouseEvent e) {
			}
		});
	}

	private void showInformationWindow(String message) {
		JOptionPane.showOptionDialog(SessionWindow.this, message, "Information", JOptionPane.PLAIN_MESSAGE,
				JOptionPane.INFORMATION_MESSAGE, null, null, null);
	}

	private String getSessionInfo() {
		String text = "Created by:\n " + resource.getOwner() + "\nShared with:\n ";
		// Group[] groups = resource.getSharingGroups();
		// Identity[] identities = resource.getSharingIdentities();

		Object[] recp = prplAppClient.getResourceManager().getResourceMetaData(resource.getURI(),
				PRPLTalk.PROPERTY_RECIPIENT_URI);

		if (recp != null) {
			for (int i = 0; i < recp.length; i++) {
				if (URIUtils.isGroupURI(recp[i].toString())) {
					text += recp[i].toString();
				} else if (URIUtils.isIdentityURI(recp[i].toString())) {
					text += recp[i].toString();
				}

				if (i < recp.length - 1)
					text += ", ";
			}
		}

		return text;
	}

	private JPanel initMessageCompose() {

		JPanel messagePanel = new JPanel(new BorderLayout());

		JPanel controlPanel = new JPanel(new GridBagLayout());
		JButton sendButton = new JButton("Send");
		sendButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				String text = messageTextArea.getText();
				text = StringUtils.trimEvenNull(text);
				prplTalk.sendMessage(sessionId, "", text);
				messageTextArea.setText("");
			}

		});
		JButton shareButton = new JButton("Share");
		shareButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				showBlobResourceBrowser();
				showInformationWindow("Shared a blob resource.");
				/*
				 * String text = messageTextArea.getText(); text = StringUtils.trimEvenNull(text); if
				 * (URIUtils.isResourceURI(text)) { prplTalk.shareResource(sessionId, text); log.debug("Sending a
				 * message to share a PrPl resource + " + text); showInformationWindow("Sharing resource message
				 * sent."); } else { log.debug("Text is not a proper PrPl URI"); showInformationWindow("Entered
				 * invalid resource URI."); } messageTextArea.setText("");
				 */
			}

		});

		JButton inviteButton = new JButton("Invite");
		inviteButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				BuddyInfo buddy = (BuddyInfo) buddyComboBox.getSelectedItem();
				if (buddy != null) {
					prplTalk.invite(sessionId, buddy.identity.getURI());
					sessionInfoTextArea.setText(getSessionInfo());
					showInformationWindow("Inviated " + buddy);
				}
			}

		});

		JButton refreshButton = new JButton("Refresh");
		refreshButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				Message[] messages = prplTalk.getMessages(sessionId, true);
				sessionInfoTextArea.setText(getSessionInfo());
				displayList.setListData(messages);
				// displayList.updateUI();
				displayList.ensureIndexIsVisible(displayList.getModel().getSize() - 1);
			}

		});

		this.buddyComboBox = new JComboBox(prplTalk.getBuddyList());

		GridBagConstraints c = new GridBagConstraints();

		c = new GridBagConstraints();
		c.gridy = 0;
		c.gridx = 0;
		c.gridwidth = 1;
		controlPanel.add(sendButton, c);

		c = new GridBagConstraints();
		c.gridy = 0;
		c.gridx = 1;
		c.gridwidth = 1;
		controlPanel.add(shareButton, c);

		c = new GridBagConstraints();
		c.gridy = 0;
		c.gridx = 2;
		c.gridwidth = 1;
		controlPanel.add(inviteButton, c);

		c = new GridBagConstraints();
		c.gridy = 0;
		c.gridx = 3;
		c.gridwidth = 1;
		controlPanel.add(buddyComboBox, c);

		c = new GridBagConstraints();
		c.gridy = 0;
		c.gridx = 4;
		c.gridwidth = 1;
		controlPanel.add(refreshButton, c);

		this.messageTextArea = new JTextArea();
		messageTextArea.setColumns(500);
		messageTextArea.setRows(10);
		// messageTextArea.setSize(500, 400);
		messageTextArea.setBorder(BorderFactory.createLineBorder(Color.BLACK));

		messagePanel.add(controlPanel, BorderLayout.NORTH);
		messagePanel.add(messageTextArea, BorderLayout.SOUTH);

		return messagePanel;
	}

	protected void showBlobResourceBrowser() {

		this.popupBox = new JDialog(this, "Select Blob Resource", true);
		JPanel msgPanel = new JPanel();
		JPanel btnPane = new JPanel();

		JScrollPane resourceScrollPane = new JScrollPane();
		final JList resourceList = new JList();
		resourceList.setListData(prplAppClient.getResourceManager().getAllBlobResources().toArray());
		resourceList.setCellRenderer(new BlobResourceListRenderer());
		resourceScrollPane.getViewport().add(resourceList);
		// resourceScrollPane.setPreferredSize(new Dimension(0, 75));

		msgPanel.add(resourceScrollPane);

		JButton ok = new JButton("Share");
		btnPane.add(ok);
		ok.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {

				BlobResource resource = (BlobResource) resourceList.getSelectedValue();
				prplTalk.shareResource(sessionId, resource.getURI());
				log.debug("Sending a  message to share a PrPl resource + " + resource);
				popupBox.setVisible(false);
				popupBox.dispose();
			}
		});

		JButton cancel = new JButton("Cancel");
		btnPane.add(cancel);
		cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				popupBox.setVisible(false);
				popupBox.dispose();
			}
		});

		popupBox.setLocation(320, 240);
		popupBox.getContentPane().add(msgPanel);
		popupBox.getContentPane().add(btnPane, BorderLayout.SOUTH);
		popupBox.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		popupBox.pack();
		popupBox.setVisible(true);
	}

	public static class MessageListRenderer extends javax.swing.DefaultListCellRenderer {

		@Override
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
				boolean cellHasFocus) {

			JPanel p = new JPanel(new BorderLayout(1, 1));
			JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
			JTextArea t = new JTextArea();

			Message message = (Message) value;

			try {

				String text = Arrays.toString(message.getFrom()) + " at " + message.getSentDate();
				// + " to " + Arrays.toString(message.getAllRecipients())

				l.setText(text);

				String messageDesc = StringUtils.trimEvenNull(message.getDescription());

				if (messageDesc.startsWith(PRPLTalk.MSG_RESOURCE)) {

					BufferedImage icon = ImageIO.read(new FileInputStream("img/download.png"));
					l.setIcon(new ImageIcon(icon));

					String content = message.getContent().toString();

					if (URIUtils.isResourceURI(content)) {

						log.trace("Msg contains (valid) resource URI.");
						t.setText("Click to download " + content);
					} else {
						log.debug("Msg contains invalid resource URI.");
						t.setText("Invalid PrPl Resource URI, " + content);
					}

				} else {// if (messageDesc.startsWith(PRPLTalk.MSG_TEXT)) {
					BufferedImage icon = ImageIO.read(new FileInputStream("img/message_icon.gif"));
					l.setIcon(new ImageIcon(icon));
					log.trace("Msg contains text.");
					String content = message.getContent().toString();
					t.setText(content);
				}
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			t.setText(t.getText() + "\n\n");
			p.add(l, BorderLayout.NORTH);
			p.add(t, BorderLayout.CENTER);
			return p;
		}
	}

	public static class BlobResourceListRenderer extends javax.swing.DefaultListCellRenderer {
		@Override
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
				boolean cellHasFocus) {

			JPanel p = new JPanel(new BorderLayout());
			JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

			try {
				BufferedImage icon = ImageIO.read(new FileInputStream("img/share.gif"));
				l.setIcon(new ImageIcon(icon));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			BlobResource resource = (BlobResource) value;
			String text = new String();
			text = resource.getName();// + " [" + resource.getLastModifiedDate().getTime() + "]";
			JTextPane t = new JTextPane();
			t.setText(text);
			t.setFont(new Font("Arial", PLAIN, 11));

			p.add(l, BorderLayout.NORTH);
			p.add(t, BorderLayout.CENTER);

			return p;
		}
	}
}
